function patchStyle(el, prevValue, nextValue) {
    const style = el["style"]
    if (nextValue) {
        for (let key in nextValue) {
            style[key] = nextValue[key]
        }
    }
    if (prevValue) {
        for (let key in prevValue) {
            if (nextValue[key] === null) {
                style[key] = null
            }
        }
    }
}

function patchClass(el, nextValue) {
    if (nextValue == null) {
        el.removeAttribute("class")
    } else {
        el.className = nextValue
    }
}

function createInvoker(val) {
    let invoker = (e) => invoker.val(e)
    invoker.val = val
    return invoker
}

function patchEvent(el, eventName, nextValue) {
    const invokers = el._vei || (el._vei = {})
    const exist = invokers[eventName]
    // click: customEvent -> f
    // 通过一个自定义变量，绑定这个变量，后需更改变量对应的值
    if (exist && nextValue) {
        // 已存在旧事件，并且有新事件
        exist.val = nextValue // 换绑事件
    } else {
        // 没有旧事件，或者没有新事件
        const name = eventName.slice(2).toLowerCase()
        // 有新事件
        if (nextValue) {
            // 绑定事件
            const invoker = (invokers[eventName] = createInvoker(nextValue))
            el.addEventListener(name, invoker)
        } else if (exist) {
            // 没有新事件，有旧事件（清空事件）
            el.removeEventListener(name, exist)
            invokers[eventName] = null
        }
    }
}

function patchAttr(el, key, nextValue) {
    if (nextValue == null) {
        el.removeAttribute(key)
    } else {
        el.setAttribute(key, nextValue)
    }
}

export function patchProps(el, key, prevValue, nextValue) {
    // 属性的初始化和更新：对于初始化 prevValue:null
    // {style:{color:red}}  -> el.style[key] = value
    if (key === 'style') {
        return patchStyle(el, prevValue, nextValue)
    } else if (key === 'class') {
        // {class:'abc'} -> el.className(class,'')
        return patchClass(el, nextValue)
    } else if (/^on[^a-z]/.test(key)) {
        // onClick -> addEventListener()
        return patchEvent(el, key, nextValue)
    } else {
        patchAttr(el, key, nextValue)
    }
}
